package com.example.template.common.aop;

import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;

/**
 * @className: LogAspect
 * @description: 日志切面类
 * @author: Kuangkeli
 * @date: 2024/01/20 15:54
 **/
@Slf4j
@Aspect
@Component
public class LogAspect {
    /**
     * 切入点：设置方法会在com.wego.controller包及其子包下的、任意访问控制修饰符修饰的、返回值为任意类型的、包含任何多个参数的、任意方法、执行之前执行
     */
    @Pointcut("execution(* com.example.template.controller..*.*(..))")
    public void fun() {
    }

    /**
     * 环绕通知
     * 第一个参数可以定义为org.aspectj.lang.ProceedingJoinPoint类型
     * @param joinPoint
     * @return
     * @throws Throwable
     */
    @Around("fun()")
    public Object doAround(ProceedingJoinPoint joinPoint) throws Throwable {
        Object result = null;

        //取得类名和方法名
        final String fullMethodName = getFullMethodName(joinPoint);

        //相当于前置通知
        log.info(fullMethodName+"方法开始执行");

        Object[] args= joinPoint.getArgs();
        log.info("参数信息为：{}  ",args);

        try {
            result = joinPoint.proceed();
            log.info("结果为：{}"+result);
        } catch (Throwable ex) {
            //相当于异常抛出后通知
            StackTraceElement stackTraceElement= ex.getStackTrace()[ex.getStackTrace().length-1];

            log.error ("{}方法的{}行",fullMethodName,stackTraceElement.getLineNumber()+"抛出异常");
            log.error("异常信息为：{}  ",ex.fillInStackTrace().toString());
            throw ex;
        }finally{
            //相当于最终通知
            log.info(fullMethodName+"方法执行结束");
        }

        return result;
    }

    private String getFullMethodName(JoinPoint joinPoint) {
        return joinPoint.getTarget().getClass().getName()
                + "."
                + joinPoint.getSignature().getName()
                +"()";
    }
}